package com.gitee.wsl.scheduler.job.runtime

import com.gitee.wsl.scheduler.job.bean.JobSettings
import com.gitee.wsl.scheduler.job.bean.ScheduledJob
import com.gitee.wsl.scheduler.job.repository.JobRepository
import com.gitee.wsl.logger.Logger
import com.gitee.wsl.logger.debug
import kotlin.time.ExperimentalTime
import kotlin.time.Instant


interface JobScheduler {
    @OptIn(ExperimentalTime::class)
    suspend fun schedule(settings: JobSettings, runAt: Instant? = null): ScheduledJob
    
    companion object
}

fun JobScheduler.Companion.create(jobRepository: JobRepository): JobScheduler = DefaultJobScheduler(jobRepository)

internal class DefaultJobScheduler(private val jobRepository: JobRepository) : JobScheduler {

    @OptIn(ExperimentalTime::class)
    override suspend fun schedule(settings: JobSettings, runAt: Instant?): ScheduledJob = settings.run {
        return if (jobRepository.exist(id)) {
            error("Job '$name' with id '$id' has already been scheduled.")
        } else {
            jobRepository.save(this, runAt).also { Logger.debug("Scheduled new job '${it.settings.name} @ '$runAt'") }
        }
    }
}